package com.brillilab.service.logic.user;

import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils;
import com.aliyun.oss.OSSClient;
import com.brillilab.common.alioss.OssUtils;
import com.brillilab.common.constant.ResultEnum;
import com.brillilab.common.constant.TimeConstant;
import com.brillilab.common.entity.ResponseVo;
import com.brillilab.common.exceptions.BrillilabException;
import com.brillilab.common.utils.CodeUtil;
import com.brillilab.common.utils.MyBeanUtils;
import com.brillilab.common.utils.ValidatorUtil;
import com.brillilab.domain.enums.lab.*;
import com.brillilab.domain.po.lab.Lab;
import com.brillilab.domain.po.lab.LabJoinAudit;
import com.brillilab.domain.po.lab.LabMember;
import com.brillilab.domain.po.user.UserInviteAudit;
import com.brillilab.domain.po.user.UserInviteRejectRecord;
import com.brillilab.domain.po.user.Users;
import com.brillilab.domain.vo.crm.CrmUsersInfoVo;
import com.brillilab.domain.vo.lab.ApplyJoinLabVo;
import com.brillilab.domain.vo.user.*;
import com.brillilab.service.core.email.impl.EmailServiceImpl;
import com.brillilab.service.core.lab.ILabJoinAuditService;
import com.brillilab.service.core.lab.ILabMemberPowerService;
import com.brillilab.service.core.lab.ILabMemberService;
import com.brillilab.service.core.lab.ILabService;
import com.brillilab.service.core.system.IDictService;
import com.brillilab.service.core.user.IUserInviteAuditService;
import com.brillilab.service.core.user.IUserInviteRejectRecordService;
import com.brillilab.service.core.user.IUsersService;
import com.brillilab.service.logic.lab.LabApplyLogic;
import com.brillilab.service.logic.message.MessageLogic;
import com.brillilab.service.logic.team.TeamLogic;
import com.brillilab.service.module.aliyun.AliYunSms;
import com.brillilab.service.module.invite.InviteSet;
import com.brillilab.service.module.message.producer.MessageProducer;
import com.brillilab.service.module.message.template.impl.usercenter.ApplyJoinLabWaitAuditTemplate;
import com.brillilab.service.module.message.template.impl.usercenter.NoMemberManageInviteSuccessTemplate;
import com.brillilab.service.module.message.template.impl.usercenter.RegisterSuccessTemplate;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class UserInviteAuditLogic {

	private static Logger logger = LoggerFactory.getLogger(UserInviteAuditLogic.class);

	@Resource
	private IUserInviteAuditService userInviteAuditService;

	@Resource
	private MessageLogic messageLogic;

	@Resource
	private UsersLogic usersLogic;

	@Resource
	private IUsersService usersService;

	@Resource
	private ILabService labService;

	@Resource
	private ILabMemberService labMemberService;

	@Resource
	private IDictService dictService;

	@Resource
	private AliYunSms aliYunSms;

	@Resource
	private OssUtils ossUtil;

	@Resource
	private EmailServiceImpl emailService;

	@Resource
	private InviteSet inviteSet;

	@Resource
	private TeamLogic teamLogic;

	@Resource
	private IUserInviteRejectRecordService userInviteRejectRecordService;
	@Resource
	private MessageProducer messageProducer;
	@Resource
	private ILabMemberPowerService labMemberPowerService;
	@Resource
	private LabApplyLogic labApplyLogic;
	@Resource
	private ILabJoinAuditService labJoinAuditService;

	/**
	 * 添加邀请申请
	 *
	 * @param userInfoVo
	 * @param sendType
	 * @param receiver
	 */
	public void addInviteAudit(UserInfoVo userInfoVo, Integer sendType, String receiver) {
		Assert.isTrue(sendType == 1 || sendType == 2, ResultEnum.REQUEST_PARAM_ERROR.getMessage());
		// 验证码生成
		String code = CodeUtil.getCode(6, "1234567890");
		// 添加申请记录
		if (sendType.equals(1)) {
			// 如果通过手机号邀请
			Assert.isTrue(ValidatorUtil.isPhone(receiver), "手机号格式错误");
			UserInviteAudit userInviteAudit = addInviteAuditByType(userInfoVo, sendType, receiver, code);
			// 发送短信验证码
			Assert.isTrue(sendMobileInviteVerifyCode(userInfoVo, receiver, userInviteAudit.getId(), code), "发送短信失败！");
		} else if (sendType.equals(2)) {
			// 如果通过email邀请
			Assert.isTrue(ValidatorUtil.isEmail(receiver), "邮箱格式错误");
			UserInviteAudit userInviteAudit = addInviteAuditByType(userInfoVo, sendType, receiver, code);
			Assert.isTrue(sendEmailInviteVerifyCode(userInfoVo, receiver, userInviteAudit.getId(), code), "发送邮件失败！");
		}
	}

	/**
	 * 校验邀请链接
	 *
	 * @param id
	 * @param code
	 * @return
	 */
	public ResponseVo getUserInviteAudit(Long id, String code) {
		UserInviteAudit userInviteAudit = userInviteAuditService.selectById(id);
		// 未找到邀请记录
		Assert.isTrue(userInviteAudit != null, "非常抱歉，您还不是我们平台开放到的用户，请您耐心等待！");
		Assert.isTrue(userInviteAudit.getInviteCode().equals(code), "邀请链接参数无效！");
		// 申请时间是否超过三天
		boolean isExpire = (new Date().getTime() - userInviteAudit.getCreateTime().getTime())
				/ 1000 < TimeConstant.THREE_DAYS;
		if (!isExpire) {
			ResponseVo failure;
			failure = ResponseVo.failure(ResultEnum.VERIFY_CODE_EXPIRE.getMessage());
			failure.setCode(ResultEnum.VERIFY_CODE_EXPIRE.getCode());
			return failure;
		}

		if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.AUDIT_PASS.getValue())) {
			return ResponseVo.success("您已成功加入了" + userInviteAudit.getLabName() + ",请您在客户端登录。",
					"您已成功加入了" + userInviteAudit.getLabName() + ",请您在客户端登录。");
		} else if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_CHECK.getValue())) {
			return ResponseVo.success("验证信息已经发送到您的邮箱，请您在邮箱中点击链接验证", "验证信息已经发送到您的邮箱，请您在邮箱中点击链接验证");
		} else if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_AUDIT.getValue())
				&& userInviteAudit.getInviteState().equals(UserAuditInviteStateEnum.SUBMIT_APPLY.getValue())) {
			// 待审核
			return ResponseVo.failure(ResultEnum.LAB_NO_PI_OR_LAB_AUDIT_WAIT_PC,
					"您的申请已经提交成功！我们会在1—3个工作日内审核完成，审核完成后会短信通知您，请您耐心等待。",
					"您的申请已经提交成功！我们会在1—3个工作日内审核完成，审核完成后会短信通知您，请您耐心等待。");
		} else {
			UserInviteAuditCodeVo userInviteAuditCodeVo = MyBeanUtils.copyBean(userInviteAudit,
					UserInviteAuditCodeVo.class);
			userInviteAuditCodeVo.setIsRegister(0);
			userInviteAuditCodeVo.setTips("");
			if (userInviteAudit.getMobile() != null) {
				Users users = usersLogic.getUser(userInviteAudit.getMobile());
				if (users != null) {
					List<LabMember> labMemberList = labMemberService.selectAllByUserId(users.getId()).stream()
							.sorted(Comparator.comparing(LabMember::getUpdateTime).reversed())
							.collect(Collectors.toList());
					if (!CollectionUtils.isEmpty(labMemberList)) {
						LabMember labMember = labMemberList.get(0);
						Map<Integer, String> dutyMap = dictService.getUserDutyMap();
						if (!CollectionUtils.isEmpty(dutyMap)) {
							dutyMap.forEach((dutyCode, dutyName) -> {
								if (dutyName.equals(labMember.getDuty())) {
									userInviteAuditCodeVo.setDuty(dutyCode);
									userInviteAuditCodeVo.setDutyName(dutyName);
								}
							});
						}
					}
					userInviteAuditCodeVo.setIsRegister(1);
					userInviteAuditCodeVo.setTips("您已注册，请填写信息后加入实验室");
					userInviteAuditCodeVo.setRealName(users.getName());
				}
			}
			return ResponseVo.success(userInviteAuditCodeVo);
		}
	}

	/**
	 * 邮件发送链接邀请
	 *
	 * @param userInfoVo
	 * @param email
	 * @param userInviteAuditId
	 * @param code
	 */
	public boolean sendEmailInviteVerifyCode(UserInfoVo userInfoVo, String email, Long userInviteAuditId, String code) {
		String param = userInviteAuditId + "_" + code;
		String title = "来自【" + userInfoVo.getLabName() + "】的注册邀请";
		String encode = Base64.getUrlEncoder().encodeToString(param.getBytes());
		encode = encode.replace("=", "");
		String url = inviteSet.getRegisterUrl() + "index.html#Invitation?param=" + encode;
		String sendHtml = "";
		// "您好，" + userInfoVo.getName() + "请您加入" + userInfoVo.getLabName() +
		// "的Lab，请点击：<a href='" + url + "' target='_blank'>" + url +
		// "</a>查看（链接3天后失效，请您尽快完成注册）。";

		InputStream resourceAsStream = this.getClass().getClassLoader()
				.getResourceAsStream("templates/inviteRegTemp.html");
		sendHtml = emailService.getEmailSender().getEmailHtml(resourceAsStream);

		// 替换信息
		sendHtml = sendHtml.replace("{inviteName}", userInfoVo.getName());
		sendHtml = sendHtml.replace("{labName}", userInfoVo.getLabName());
		sendHtml = sendHtml.replace("{inviteUrl}", url);

		return messageLogic.sendEmail(title, sendHtml, email);
	}

	/**
	 * 手机发送链接邀请
	 *
	 * @param userInfoVo
	 * @param mobile
	 * @param userInviteAuditId
	 * @param code
	 */
	public boolean sendMobileInviteVerifyCode(UserInfoVo userInfoVo, String mobile, Long userInviteAuditId,
			String code) {
		Map<String, Object> paramMap = new HashMap<>();
		// paramMap.put("inviteName", userInfoVo.getName());
		paramMap.put("labName", userInfoVo.getLabName());
		String param = userInviteAuditId + "_" + code;
		String encode = Base64.getUrlEncoder().encodeToString(param.getBytes());
		encode = encode.replace("=", "");
		paramMap.put("param", encode + " ");// 加空格解决ios手机链接打开地址有误的问题
		return messageLogic.sendSmsContent(mobile, aliYunSms.getInviteUserRegisterTemplate(), paramMap);
	}

	/**
	 * 添加申请邀请记录
	 *
	 * @param userInfoVo
	 * @param sendType
	 * @param receiver
	 * @param code
	 * @return
	 */
	public UserInviteAudit addInviteAuditByType(UserInfoVo userInfoVo, Integer sendType, String receiver, String code) {
		UserInviteAudit userInviteAudit = new UserInviteAudit();
		userInviteAudit.setInviteType(2);
		userInviteAudit.setInviteUser(userInfoVo.getId());
		userInviteAudit.setLabId(userInfoVo.getLabId());
		userInviteAudit.setState(0);
		userInviteAudit.setInviteCode(code);
		userInviteAudit.setLabName(userInfoVo.getLabName());
		userInviteAudit.setInviteState(0);// 默认邀请状态为0 邀请中
		if (sendType == 1) {
			userInviteAudit.setMobile(receiver);

		} else if (sendType == 2) {
			userInviteAudit.setEmail(receiver);
		}
		boolean isSuccess = userInviteAuditService.save(userInviteAudit);
		Assert.isTrue(isSuccess, "添加邀请记录失败");
		return userInviteAudit;
	}

	/**
	 * 提交实验室成员申请
	 *
	 * @param applyInfoVo
	 * @return
	 */
	public UserInviteAudit submitLabMemberApply(UserInviteApplyInfoVo applyInfoVo, UserInfoVo userInfoVo) {
		UserInviteAudit userInviteAudit = userInviteAuditService.selectById(applyInfoVo.getApplyId());
		Long applyId = 0l;
		if (userInviteAudit != null) {
			if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_AUDIT.getValue())
					&& userInviteAudit.getInviteState().equals(UserAuditInviteStateEnum.SUBMIT_APPLY.getValue())) {
				// code 2001 前端那边页面需要
				throw new BrillilabException(ResultEnum.LAB_NO_PI_OR_LAB_AUDIT_WAIT_PC,
						"您的申请已经提交，我们会在1-3个工作日内审核完成，审核完成后短信通知您，请您耐心等待！");
			}
			Assert.isTrue(userInviteAudit.getState() != 1, "您的申请已经通过，请勿重复提交！");

			userInviteAudit.setInviteState(UserAuditInviteStateEnum.SUBMIT_APPLY.getValue());// 邀请状态改为提交中
			// 审核失败再次申请，申请状态置为待审核
			if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.AUDIT_NOT_PASS.getValue())) {
				userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_AUDIT.getValue());
			}
			applyId = userInviteAudit.getId();
		}
		// 首次申请
		if (userInviteAudit == null) {
			userInviteAudit = new UserInviteAudit();
			userInviteAudit.setId(0l);
		}
		userInviteAudit.setId(applyId);
		BeanUtils.copyProperties(applyInfoVo, userInviteAudit);

		if (userInfoVo != null) {
			Lab lab = labService.selectById(userInfoVo.getLabId());
			userInviteAudit.setInviteType(UserAuditInviteTypeEnum.INVITE_NORMAL.getValue());// 添加新成员，默认邀请类型为2
			userInviteAudit.setInviteUser(userInfoVo.getId());
			userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_AUDIT.getValue());
			userInviteAudit.setLabId(userInfoVo.getLabId());
			userInviteAudit.setLabName(lab.getName());
			userInviteAudit.setInviteState(1);// 添加新成员，默认邀请状态为1已提交
		}
		if (StringUtils.isNotEmpty(userInviteAudit.getOrgEmail())) {
			// 机构邮箱
			String orgEmail = userInviteAudit.getOrgEmail();
			userInviteAudit.setState(0);// 默认为待审核
			boolean isRightEmail = labApplyLogic.checkEmailFormat(orgEmail);
			if (isRightEmail) {
				// 包含学术邮箱后缀，执行邮箱验证
				userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_CHECK.getValue());
				String code = CodeUtil.getCode(6, "1234567890");
				// 验证码
				userInviteAudit.setInviteCode(code);
			}

		} else {
			Assert.isTrue(StringUtils.isNotEmpty(userInviteAudit.getCardImg()), "请上传证件照片！");
			Assert.isTrue(StringUtils.isNotEmpty(userInviteAudit.getCertificateNo()), "证件号不能为空！");
			Assert.isTrue(userInviteAudit.getCardImg().contains(","), "证件照参数不合法，请核实！");
			userInviteAudit.setState(0);
		}
		// 执行申请记录插入
		userInviteAudit.setPassword(DigestUtils.md5Hex(userInviteAudit.getPassword()).toUpperCase());
		userInviteAudit.setSecurityPwd(DigestUtils.md5Hex(userInviteAudit.getSecurityPwd()).toUpperCase());
		if (userInviteAudit.getId().equals(0l)) {
			userInviteAudit = userInviteAuditService.insert(userInviteAudit);
		} else {
			// 再次申请
			userInviteAudit.setUpdateTime(new Date());
			userInviteAudit.setAuditInfo("");
			userInviteAuditService.updateById(userInviteAudit);
		}

		if (StringUtils.isNotBlank(userInviteAudit.getOrgEmail())
				&& userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_CHECK.getValue())) {
			// 发送邮箱验证的邮件
			String param = "2_" + userInviteAudit.getId() + "_" + userInviteAudit.getInviteCode();
			String encode = Base64.getUrlEncoder().encodeToString(param.getBytes());
			encode = encode.replace("=", "");
			String url = inviteSet.getRegisterUrl() + "index.html#registerCheck?param=" + encode;
			String title = "【LabInOne】用户邮箱验证";
			String sendHtml = "";
//                    "尊敬的" + userInviteAudit.getRealName() + "先生/女士，您好，请您点击验证您的信息：" +
//                    "<a href='" + url + "' target='_blank'>" + url + "</a>，感谢您关注布理岚柏平台。";

			InputStream resourceAsStream = this.getClass().getClassLoader()
					.getResourceAsStream("templates/emailValidateTemp.html");
			sendHtml = emailService.getEmailSender().getEmailHtml(resourceAsStream);

			// 替换信息
			sendHtml = sendHtml.replace("{realName}", userInviteAudit.getRealName());
			sendHtml = sendHtml.replace("{validateUrl}", url);
			messageLogic.sendEmail(title, sendHtml, userInviteAudit.getOrgEmail());
		}

		return userInviteAudit;
	}

	/**
	 * 提交申请加入实验室
	 *
	 * @param applyJoinLabVo
	 * @return
	 */
	public UserInviteAudit submitApplyJoinLab(ApplyJoinLabVo applyJoinLabVo) {
		Lab lab = labService.selectById(applyJoinLabVo.getLabId());
		Assert.notNull(lab, "实验室信息有误");

		UserInviteAudit userInviteAudit = userInviteAuditService.selectByLabIdAndMobile(applyJoinLabVo.getLabId(),
				applyJoinLabVo.getMobile());
		if (userInviteAudit != null) {
			if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_AUDIT.getValue())
					&& userInviteAudit.getInviteState().equals(UserAuditInviteStateEnum.SUBMIT_APPLY.getValue())) {
				// code 2001 前端那边页面需要
				throw new BrillilabException(ResultEnum.LAB_NO_PI_OR_LAB_AUDIT_WAIT_PC,
						"您的申请已经提交，我们会在1-3个工作日内审核完成，审核完成后短信通知您，请您耐心等待！");
			} else if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_CHECK.getValue())) {
				throw new BrillilabException(ResultEnum.LAB_NO_PI_OR_LAB_AUDIT_WAIT_PC, "验证信息已经发送到您的机构邮箱，请查收邮件进行验证！");
			} else if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_PI_AUDIT.getValue())) {
				throw new BrillilabException(ResultEnum.LAB_NO_PI_OR_LAB_AUDIT_WAIT_PC, "您的申请已经提交，需要PI审核成功后才可以加入实验室！");
			}
			Assert.isTrue(userInviteAudit.getState() != 1, "您的申请已经通过，请勿重复提交！");

			userInviteAudit.setInviteState(1);// 邀请状态改为提交中
			// 审核失败再次申请，申请状态置为待审核
			if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.AUDIT_NOT_PASS.getValue())) {
				userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_AUDIT.getValue());
			}
		}
		// 首次申请
		if (userInviteAudit == null) {
			userInviteAudit = new UserInviteAudit();
			userInviteAudit.setId(0l);
		}
		BeanUtils.copyProperties(applyJoinLabVo, userInviteAudit);

		if (lab != null) {
			userInviteAudit.setInviteType(UserAuditInviteTypeEnum.ACTIVE_JOIN.getValue());// 邀请类型为：成员主动申请
			userInviteAudit.setInviteUser(0L);
			userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_AUDIT.getValue());
			userInviteAudit.setLabId(lab.getId());
			userInviteAudit.setLabName(lab.getName());
			userInviteAudit.setInviteState(UserAuditInviteStateEnum.SUBMIT_APPLY.getValue());// 添加新成员，默认邀请状态为1已提交
		}
		if (StringUtils.isNotEmpty(userInviteAudit.getOrgEmail())) {
			// 机构邮箱
			String orgEmail = userInviteAudit.getOrgEmail();
			userInviteAudit.setState(0);// 默认为待审核
			boolean isRightEmail = labApplyLogic.checkEmailFormat(orgEmail);
			if (isRightEmail) {
				// 包含学术邮箱后缀，执行邮箱验证
				userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_CHECK.getValue());
				String code = CodeUtil.getCode(6, "1234567890");
				// 验证码
				userInviteAudit.setInviteCode(code);
			}

		} else {
			Assert.isTrue(StringUtils.isNotEmpty(userInviteAudit.getCardImg()), "请上传证件照片！");
			Assert.isTrue(StringUtils.isNotEmpty(userInviteAudit.getCertificateNo()), "证件号不能为空！");
			Assert.isTrue(userInviteAudit.getCardImg().contains(","), "证件照参数不合法，请核实！");
			userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_AUDIT.getValue());
		}
		// 执行申请记录插入
		userInviteAudit.setPassword(DigestUtils.md5Hex(userInviteAudit.getPassword()).toUpperCase());
		userInviteAudit.setSecurityPwd(DigestUtils.md5Hex(userInviteAudit.getSecurityPwd()).toUpperCase());
		if (userInviteAudit.getId().equals(0L)) {
			userInviteAudit = userInviteAuditService.insert(userInviteAudit);
		} else {
			// 再次申请
			userInviteAudit.setUpdateTime(new Date());
			userInviteAudit.setAuditInfo("");
			userInviteAuditService.updateById(userInviteAudit);
		}

		if (StringUtils.isNotBlank(userInviteAudit.getOrgEmail())
				&& userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_CHECK.getValue())) {
			// 发送邮箱验证的邮件
			String param = "2_" + userInviteAudit.getId() + "_" + userInviteAudit.getInviteCode();
			String encode = Base64.getUrlEncoder().encodeToString(param.getBytes());
			encode = encode.replace("=", "");
			String url = inviteSet.getRegisterUrl() + "index.html#registerCheck?param=" + encode;
			String title = "【LabInOne】用户邮箱验证";
			String sendHtml = "";
//                    "尊敬的" + applyJoinLabVo.getRealName() + "先生/女士，您好，请您点击验证您的信息：" +
//                    "<a href='" + url + "' target='_blank'>" + url + "</a>，感谢您关注布理岚柏平台。";

			InputStream resourceAsStream = this.getClass().getClassLoader()
					.getResourceAsStream("templates/emailValidateTemp.html");
			sendHtml = emailService.getEmailSender().getEmailHtml(resourceAsStream);

			// 替换信息
			sendHtml = sendHtml.replace("{realName}", applyJoinLabVo.getRealName());
			sendHtml = sendHtml.replace("{validateUrl}", url);

			messageLogic.sendEmail(title, sendHtml, applyJoinLabVo.getOrgEmail());
		}

		return userInviteAudit;
	}

	/**
	 * 申请加入实验室【免去邮箱验证】
	 *
	 * @param applyJoinLabVo
	 * @return
	 */
	public ResponseVo autoApplyJoinLab(ApplyJoinLabVo applyJoinLabVo) {
		Lab lab = labService.selectById(applyJoinLabVo.getLabId());
		Assert.notNull(lab, "实验室信息有误");

		UserInviteAudit userInviteAudit = userInviteAuditService.selectByLabIdAndMobile(lab.getId(),
				applyJoinLabVo.getMobile());
		if (userInviteAudit != null) {
			if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_AUDIT.getValue())
					&& userInviteAudit.getInviteState().equals(UserAuditInviteStateEnum.SUBMIT_APPLY.getValue())) {
				// code 2001 前端那边页面需要
				throw new BrillilabException(ResultEnum.LAB_NO_PI_OR_LAB_AUDIT_WAIT_PC,
						"您的申请已经提交，我们会在1-3个工作日内审核完成，审核完成后短信通知您，请您耐心等待！");
			} else if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_CHECK.getValue())) {
				throw new BrillilabException(ResultEnum.LAB_NO_PI_OR_LAB_AUDIT_WAIT_PC, "验证信息已经发送到您的机构邮箱，请查收邮件进行验证！");
			} else if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.WAIT_PI_AUDIT.getValue())) {
				throw new BrillilabException(ResultEnum.LAB_NO_PI_OR_LAB_AUDIT_WAIT_PC, "您的申请已经提交，需要PI审核成功后才可以加入实验室！");
			}
			Assert.isTrue(userInviteAudit.getState() != 1, "您的申请已经通过，请勿重复提交！");

			userInviteAudit.setInviteState(1);// 邀请状态改为提交中
			// 审核失败再次申请，申请状态置为待审核
			if (userInviteAudit.getState().equals(UserInviteAuditStateEnum.AUDIT_NOT_PASS.getValue())) {
				userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_AUDIT.getValue());
			}
		}
		// 首次申请
		if (userInviteAudit == null) {
			userInviteAudit = new UserInviteAudit();
			userInviteAudit.setId(0l);
		}
		BeanUtils.copyProperties(applyJoinLabVo, userInviteAudit);

		if (lab != null) {
			userInviteAudit.setInviteType(UserAuditInviteTypeEnum.ACTIVE_JOIN.getValue());// 邀请类型为：成员主动申请
			userInviteAudit.setInviteUser(0L);
			userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_AUDIT.getValue());
			userInviteAudit.setLabId(lab.getId());
			userInviteAudit.setLabName(lab.getName());
			userInviteAudit.setInviteState(UserAuditInviteStateEnum.SUBMIT_APPLY.getValue());// 添加新成员，默认邀请状态为1已提交
		}
		if (StringUtils.isNotEmpty(userInviteAudit.getOrgEmail())) {
			// 机构邮箱
			String orgEmail = userInviteAudit.getOrgEmail();
			userInviteAudit.setState(0);// 默认为待审核
			boolean isRightEmail = labApplyLogic.checkEmailFormat(orgEmail);
			if (isRightEmail) {
				// 包含学术邮箱后缀，执行邮箱验证
				userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_CHECK.getValue());
				String code = CodeUtil.getCode(6, "1234567890");
				// 验证码
				userInviteAudit.setInviteCode(code);
			}

		} else {
			Assert.isTrue(StringUtils.isNotEmpty(userInviteAudit.getCardImg()), "请上传证件照片！");
			Assert.isTrue(StringUtils.isNotEmpty(userInviteAudit.getCertificateNo()), "证件号不能为空！");
			Assert.isTrue(userInviteAudit.getCardImg().contains(","), "证件照参数不合法，请核实！");
			userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_AUDIT.getValue());
		}
		// 执行申请记录插入
		userInviteAudit.setPassword(DigestUtils.md5Hex(userInviteAudit.getPassword()).toUpperCase());
		userInviteAudit.setSecurityPwd(DigestUtils.md5Hex(userInviteAudit.getSecurityPwd()).toUpperCase());
		if (userInviteAudit.getId().equals(0L)) {
			userInviteAudit = userInviteAuditService.insert(userInviteAudit);
		} else {
			// 再次申请
			userInviteAudit.setUpdateTime(new Date());
			userInviteAudit.setAuditInfo("");
			userInviteAuditService.updateById(userInviteAudit);
		}

		// 执行审核通过的逻辑处理
		boolean isHaveUserManagePower = auditPass(userInviteAudit);

		String msg;// 提示信息
		if (StringUtils.isNotBlank(applyJoinLabVo.getOrgEmail())) {
			// 机构邮箱验证逻辑
			if (isHaveUserManagePower) {
				msg = "您已成功加入了" + userInviteAudit.getLabName() + "，请您在客户端登录。";
			} else {
				msg = "您的申请已提交，请您耐心等待实验室PI审核";
			}
		} else {
			// crm后台审核逻辑
			msg = "操作成功";
		}
		return ResponseVo.success("SUCCESS", msg);
	}

	/**
	 * 成员审核通过
	 *
	 * @param userInviteAudit
	 */
	public boolean auditPass(UserInviteAudit userInviteAudit) {
		Users users = usersLogic.getUser(userInviteAudit.getMobile());

		// 判断邀请人是否有成员管理权限
		boolean isHaveUserManagePower = true;
		Lab lab = labService.selectById(userInviteAudit.getLabId());
		Assert.isTrue(lab != null, "实验室不存在，请核实！");

		if (userInviteAudit.getInviteUser().equals(0L)) {
			// 无邀请人的申请记录按无成员管理权限处理
			isHaveUserManagePower = false;
		} else {
			// 有邀请人时，需判断其是否有成员管理权限(邀请人为非PI时检测权限)
			if (!lab.getOwnerId().equals(userInviteAudit.getInviteUser())) {
				LabMember inviteUserLabMember = labMemberService.selectMember(lab.getId(),
						userInviteAudit.getInviteUser());
				isHaveUserManagePower = labMemberPowerService.isPower(lab.getId(), inviteUserLabMember.getId(),
						LabMemberPowerEnum.Power.USER_MANAGE);
			}
		}
		if (users == null) {
			// 新用户
			// 用户数据初始化
			if (!isHaveUserManagePower) {
				// 无成员管理权限邀请或主动申请加入实验室时，默认不做实验室ID的初始化
				users = usersLogic.createUsersAndInsert(null, userInviteAudit.getMobile(),
						userInviteAudit.getPassword(), userInviteAudit.getRealName(),
						userInviteAudit.getCertificateNo());
			} else {
				users = usersLogic.createUsersAndInsert(userInviteAudit.getLabId(), userInviteAudit.getMobile(),
						userInviteAudit.getPassword(), userInviteAudit.getRealName(),
						userInviteAudit.getCertificateNo());
			}
			if (users != null) {
				// 密码处理
				users.setPassword(userInviteAudit.getPassword());
				users.setSecurityPwd(userInviteAudit.getSecurityPwd());
				users.setEmail(userInviteAudit.getOrgEmail());
				users.setCardImg(userInviteAudit.getCardImg());
				usersService.updateById(users);
			}
		}
		else {
			//老用户,若实验室为空，则分配当前加入的实验室
			if(users.getLabId()==null){
				users.setLabId(userInviteAudit.getLabId());
				usersService.updateById(users);
			}
			//邮箱地址更新
			if(StringUtils.isEmpty(users.getEmail()) && StringUtils.isNotBlank(userInviteAudit.getOrgEmail())){
				users.setEmail(userInviteAudit.getOrgEmail());
				usersService.updateById(users);
			}
		}

		// 邀请类型为管理员时，需要更新实验室管理员信息
		if (userInviteAudit.getInviteType() == 1) {
			// 实验室管理员赋值
			lab.setOwnerId(users.getId());
			labService.updateById(lab);
		}

		if (userInviteAudit.getInviteUser() >= 0) {
			if (!isHaveUserManagePower) {
				// 无成员管理权限的邀请人，需要通知PI执行申请加入实验室的审核，录入加入实验室审核表数据

				// 查询此用户是否存在待PI审核的记录
				LabJoinAudit labJoinAudit = labJoinAuditService.selectOne(users.getId(), lab.getId(),
						LabJoinAuditStateEnum.WAIT);
				if (labJoinAudit == null) {
					labJoinAudit = new LabJoinAudit();
					BeanUtils.copyProperties(users, labJoinAudit);
					labJoinAudit.setLabId(lab.getId());
					labJoinAudit.setUserId(users.getId());
					labJoinAudit.setCreateTime(new Date());
					labJoinAudit.setUpdateTime(new Date());
					labJoinAudit.setState(0);// 默认为待审核
					if (userInviteAudit.getInviteType() == 1) {
						// 实验室管理员职务设为PI
						labJoinAudit.setDuty("PI");
					} else {
						Map<Integer, String> userDutyMap = dictService.getUserDutyMap();
						if (userDutyMap != null) {
							labJoinAudit.setDuty(userDutyMap.get(userInviteAudit.getDuty()));
						}
					}
					labJoinAuditService.insert(labJoinAudit);
				}

				// 审核状态改为待PI审核
				userInviteAudit.setState(UserInviteAuditStateEnum.WAIT_PI_AUDIT.getValue());
				userInviteAuditService.updateById(userInviteAudit);

				// 实验室PI信息
				LabMember ownerInfo = labMemberService.getOwner(lab.getId());
				// 若邀请人无成员管理权限，则需推送消息给PI进行审核
				if (userInviteAudit.getInviteUser() > 0) {
					NoMemberManageInviteSuccessTemplate noMemberManageInviteSuccessTemplate = new NoMemberManageInviteSuccessTemplate(
							lab.getId(), ownerInfo.getUserId(), ownerInfo.getId(), lab.getName(), users.getName(),
							users.getId());
					// 执行消息推送
					messageProducer.sendMessagePush(noMemberManageInviteSuccessTemplate);
				} else {
					// 主动申请加入实验室用户，推送PI审核
					ApplyJoinLabWaitAuditTemplate applyJoinLabWaitAuditTemplate = new ApplyJoinLabWaitAuditTemplate(
							lab.getId(), ownerInfo.getUserId(), ownerInfo.getId(), lab.getName(), users.getName(),
							users.getId());
					// 执行消息推送
					messageProducer.sendMessagePush(applyJoinLabWaitAuditTemplate);
				}

				// 无成员管理权限的人邀请成员成功后给PI发送短信
				Users piUser = usersLogic.getUser(ownerInfo.getUserId());// PI
				Users inviteUser = usersLogic.getUser(userInviteAudit.getInviteUser());// 邀请人

				if (inviteUser != null) {
					// 邀请人邀请成员加入实验室，验证或审核审核成功后，通知PI审核短信
					Map<String, Object> paramMap = new LinkedHashMap<>();
					paramMap.put("PIName", piUser.getName());
					paramMap.put("InviteName", inviteUser.getName());
					paramMap.put("LabName", lab.getName());
					// 执行短信发送
					messageLogic.sendSmsContent(piUser.getMobile(),
							aliYunSms.getNoAuthInviteMemberNoticePIAuditTemplate(), paramMap);
				} else {
					// 成员主动申请加入实验室，验证或审核成功后通知PI审核短信
					Map<String, Object> paramMap = new LinkedHashMap<>();
					paramMap.put("PIName", piUser.getName());
					paramMap.put("ApplyName", userInviteAudit.getRealName());// 申请人姓名

					// logger.info("applyJoinLab，通知PI审核:"+JSON.toJSONString(paramMap));
					// 执行短信发送
					messageLogic.sendSmsContent(piUser.getMobile(),
							aliYunSms.getApplyJoinLabAuditPassNoticePIAuditTemplate(), paramMap);
				}

				// 无成员管理权限的人邀请成员成功后给被邀请的人发送短信
				Map<String, Object> param = new LinkedHashMap<>();
				param.put("realName", users.getName());
				param.put("labName", lab.getName());
				// 执行短信发送
				messageLogic.sendSmsContent(users.getMobile(),
						aliYunSms.getNoAuthInviteMemberSuccessNoticeBeInviterTemplate(), param);
			}
		}

		// 有成员管理权限的邀请人
		if (isHaveUserManagePower) {
			// 邀请人有成员管理员权限
			Long labMemberId = 0l;
			LabMember labMemberInfo = labMemberService.selectMemberAllState(userInviteAudit.getLabId(), users.getId());
			if (labMemberInfo == null) {
				// 实验室成员信息初始化
				LabMember labMember = new LabMember();
				labMember.setLabId(userInviteAudit.getLabId());
				labMember.setUserId(users.getId());
				labMember.setState(1);
				if (userInviteAudit.getInviteType() == 1) {
					// 实验室管理员职务设为PI
					labMember.setDuty("PI");
				} else {
					Map<Integer, String> userDutyMap = dictService.getUserDutyMap();
					if (userDutyMap != null) {
						labMember.setDuty(userDutyMap.get(userInviteAudit.getDuty()));
					}
				}
				labMember.setEntryDate(new Date());
				LabMember initLabMember = labMemberService.add(labMember);

				labMemberId = initLabMember != null ? initLabMember.getId() : 0;
				if (initLabMember != null && userInviteAudit.getInviteType() == 1) {
					// 初始化PI小组
					teamLogic.createOwnerTeam(lab.getId(), users.getId());
				}
			} else {
				// 若是已经存在用户且被移除，则更新实验室成员用户状态为正常
				if (labMemberInfo != null
						&& LabMemberEnum.State.STATE_OUT.getValue().equals(labMemberInfo.getState())) {
					labMemberId = labMemberInfo.getId();
					labMemberInfo.setState(LabMemberEnum.State.STATE_IN.getValue());
					labMemberService.updateById(labMemberInfo);
				}
			}

			// 初始化待审核用户记录
			initEventAuditRecord(lab.getId(), users, userInviteAudit.getInviteUser(), userInviteAudit.getLabName(),
					labMemberId);

			// 审核通过，发送“成员加入实验室成功”
			Map<String, Object> paramMap = new LinkedHashMap<>();
			paramMap.put("realName", userInviteAudit.getRealName());
			paramMap.put("labName", userInviteAudit.getLabName());
			// 执行短信发送
			messageLogic.sendSmsContent(userInviteAudit.getMobile(), aliYunSms.getMemberJoinLabSuccessTemplate(),
					paramMap);
		}

		return isHaveUserManagePower;
	}

	/**
	 * 初始化待审核用户记录
	 *
	 * @param labId        实验室ID
	 * @param users        新加入用户
	 * @param inviteUserId 邀请用户ID
	 * @param labName      实验室名称
	 * @param labMemberId  新加入用户成员Id
	 */
	public void initEventAuditRecord(Long labId, Users users, Long inviteUserId, String labName, Long labMemberId) {
		// 实验室PI信息
		LabMember ownerInfo = labMemberService.getOwner(labId);
		// 过滤PI添加新成员的审核记录,以及PI自己注册成功的记录
		if (!inviteUserId.equals(ownerInfo.getUserId()) && !users.getId().equals(ownerInfo.getUserId())) {
			// 初始化用户待审核记录
			RegisterSuccessTemplate registerSuccessTemplate = new RegisterSuccessTemplate(labId, ownerInfo.getUserId(),
					ownerInfo.getId(), labName, users.getName(), users.getId());
			// 补充消息推送的功能
			messageProducer.sendMessagePush(registerSuccessTemplate);
		}

	}

	public UserInviteAuditVo getUserInviteAuditById(Long id) {
		UserInviteAudit userInviteAudit = userInviteAuditService.selectById(id);
		Assert.isTrue(userInviteAudit != null, "无该申请成员！");
		UserInviteAuditVo userInviteAuditVo = MyBeanUtils.copyBean(userInviteAudit, UserInviteAuditVo.class);
		// 设置pi信息
		Assert.isTrue(userInviteAudit.getLabId() != null, "该申请记录无实验室ID！");
		Lab lab = labService.selectById(userInviteAudit.getLabId());
		Assert.isTrue(userInviteAudit.getLabId() != null, "无实验室！");
		if (lab != null) {
			userInviteAuditVo.setOrgId(lab.getOrgId());
			userInviteAuditVo.setOrgName(lab.getOrgName());
			userInviteAuditVo.setSecOrgName(lab.getAcademy());
			userInviteAuditVo.setLabLogo(lab.getImageUrl());
			userInviteAuditVo.setOrgId(lab.getOrgId());
			// 邀请类型为PI，显示PI的职务
			if (userInviteAudit.getInviteType().equals(1)) {
				LabMember labMember = labMemberService.selectMember(lab.getId(), lab.getOwnerId());
				if (labMember != null) {
					userInviteAuditVo.setDutyName(labMember.getDuty());
					userInviteAuditVo.setEntryTime(labMember.getEntryDate());
				}
			} else {
				// 邀请类型为非PI，显示对应的职务名称
				Map<Integer, String> userDutyMap = dictService.getUserDutyMap();
				if (userDutyMap != null) {
					userInviteAuditVo.setDutyName(userDutyMap.get(userInviteAudit.getDuty()));
				}
			}

			Users users = usersLogic.getUser(lab.getOwnerId());
			if (users != null) {
				userInviteAuditVo.setPiName(users.getName());
			}
		}

		if (StringUtils.isEmpty(userInviteAuditVo.getLabLogo())) {
			// 若实验室logo为空,返回默认头像
			userInviteAuditVo
					.setLabLogo("https://labinone-public.oss-cn-hangzhou.aliyuncs.com/image/default/lab_default.png");
		}
		// 证件照处理
		if (StringUtils.isNotEmpty(userInviteAuditVo.getCardImg())) {
			String[] imgArr = userInviteAuditVo.getCardImg().split(",");
			String bucketName = imgArr[0];
			String objectName = imgArr[1];
			OSSClient ossClient = ossUtil.initClient();
			userInviteAuditVo.setCardImg(ossUtil.getAccessUrl(ossClient, bucketName, objectName));
		}

		return userInviteAuditVo;
	}

	/**
	 * 审核实验室成员
	 *
	 * @param userAuditVo
	 * @param crmUsersInfoVo
	 * @return
	 */
	public ResponseVo auditUser(UserAuditVo userAuditVo, CrmUsersInfoVo crmUsersInfoVo) {
		UserInviteAudit userInviteAudit = userInviteAuditService.selectById(userAuditVo.getApplyId());
		Assert.notNull(userInviteAudit, "成员信息不存在，请核实！");
		Assert.isTrue(userInviteAudit.getState() != 1, "此成员已经审核通过！");
		Assert.isTrue(userInviteAudit.getInviteState() != 0, "此成员邀请状态有误！");
		userInviteAudit.setState(userAuditVo.getApplyState());
		if (userAuditVo.getApplyState().equals(1)) {
			userInviteAudit.setInviteState(2);// 邀请状态置为邀请成功
		}
		if (userAuditVo.getApplyState().equals(2)) {
			userInviteAudit.setInviteState(UserAuditInviteStateEnum.INVITE_FAIL.getValue());// 邀请状态置为邀请失败
		}

		userInviteAudit.setAuditTime(new Date());
		userInviteAudit.setUpdateTime(new Date());
		userInviteAudit.setAuditInfo(userAuditVo.getAuditInfo());
		userInviteAudit.setOperator(crmUsersInfoVo.getId());

		boolean b = userInviteAuditService.updateById(userInviteAudit);
		if (b) {
			if (userAuditVo.getApplyState() == 1) {
				// 执行审核通过的逻辑处理
				auditPass(userInviteAudit);
			} else {
				// 审核未通过，录入拒绝记录
				UserInviteRejectRecord userInviteRejectRecord = new UserInviteRejectRecord();
				userInviteRejectRecord.setUserInviteId(userInviteAudit.getId());
				userInviteRejectRecord.setAuditInfo(userAuditVo.getAuditInfo());
				userInviteRejectRecord.setOperatorId(crmUsersInfoVo.getId());
				userInviteRejectRecord.setOperatorName(crmUsersInfoVo.getRealName());
				userInviteRejectRecordService.insert(userInviteRejectRecord);

				// 审核未通过，发送“成员申请加入实验室审核未通过”短信
				Map<String, Object> paramMap = new LinkedHashMap<>();
				paramMap.put("realName", userInviteAudit.getRealName());
				paramMap.put("labName", userInviteAudit.getLabName());
				paramMap.put("failReason", userInviteAudit.getAuditInfo());
				// 执行短信发送
				messageLogic.sendSmsContent(userInviteAudit.getMobile(),
						aliYunSms.getMemberApplyJoinLabNotAdoptedTemplate(), paramMap);
			}
			return ResponseVo.success("操作成功");
		} else {
			return ResponseVo.failure("操作失败！");
		}
	}

	/**
	 * 检测申请加入实验室验证码
	 *
	 * @param id
	 * @param code
	 * @return
	 */
	public ResponseVo checkApplyJoinLabCode(Long id, String code) {
		UserInviteAudit userInviteAudit = userInviteAuditService.selectById(id);
		Assert.notNull(userInviteAudit, "无此申请加入实验室记录！");
		if (userInviteAudit.getState().equals(1)) {
			return ResponseVo.success("Success", "您已成功加入了" + userInviteAudit.getLabName() + "，请您在客户端登录。");
		}
		Assert.isTrue(userInviteAudit.getState() != 0, "您的申请正在审核中！");
		Assert.isTrue(userInviteAudit.getState() != 2, "您的申请未通过，请核实信息重新提交！");
		Assert.isTrue(userInviteAudit.getState() != 4, "您的申请已提交，需等待PI审核才能加入实验室！");
		Assert.isTrue(userInviteAudit.getInviteCode().equals(code), "验证码不正确！");
		// 申请时间是否超过三天
		boolean isExpire = (new Date().getTime() - userInviteAudit.getCreateTime().getTime())
				/ 1000 < TimeConstant.THREE_DAYS;

		if (!isExpire) {
			ResponseVo failure;
			failure = ResponseVo.failure(ResultEnum.VERIFY_CODE_EXPIRE.getMessage());
			failure.setCode(ResultEnum.VERIFY_CODE_EXPIRE.getCode());
			return failure;
		}

		// 验证成功，执行实验室审核通过处理
		userInviteAudit.setState(UserInviteAuditStateEnum.AUDIT_PASS.getValue());
		userInviteAudit.setAuditTime(new Date());
		userInviteAudit.setUpdateTime(new Date());

		boolean b = userInviteAuditService.updateById(userInviteAudit);
		Assert.isTrue(b, "验证失败！");

		// 执行审核通过的逻辑处理
		boolean isHaveUserManagePower = auditPass(userInviteAudit);

		String msg;// 提示信息
		if (isHaveUserManagePower) {
			msg = "您已成功加入了" + userInviteAudit.getLabName() + "，请您在客户端登录。";
		} else {
			msg = "您的申请已提交，请您耐心等待实验室PI审核";
		}
		return ResponseVo.success("SUCCESS", msg);
	}

}
